package com.huawei.util;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import java.io.FileInputStream;
import java.io.IOException;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 使用 Apache POI 读取 Excel 文件（支持 .xls 和 .xlsx）
 * 返回原始 Java 对象类型（Object），保留数值、日期、布尔等原始语义
 */
public class ApachePOIExcelObjectReader {

    /**
     * 读取 Excel 文件，返回 List<List<Object>>
     *
     * @param filePath 文件路径（支持 .xls 和 .xlsx）
     * @return 表格数据，每行是一个 List<Object>，空单元格为 null
     * @throws IOException 文件读取异常
     */
    public static List<List<Object>> readToList(String filePath) throws IOException {
        List<List<Object>> data = new ArrayList<>();

        try (FileInputStream fis = new FileInputStream(filePath);
             Workbook workbook = getWorkbook(fis, filePath)) {

            Sheet sheet = workbook.getSheetAt(0); // 读取第一个工作表

            // ✅ 使用 getLastRowNum() 获取最大行索引（包含空行）
            int lastRowNum = sheet.getLastRowNum();

            // 如果 sheet 为空，lastRowNum 可能为 -1
            if (lastRowNum < 0) {
                return data; // 返回空列表
            }

            // 遍历从 0 到 lastRowNum 的每一行（包括空行）
            for (int rowIndex = 0; rowIndex <= lastRowNum; rowIndex++) {
                Row row = sheet.getRow(rowIndex); // 可能为 null（表示整行为空）

                List<Object> rowData = new ArrayList<>();

                if (row == null) {
                    // 整行为空：需要确定列数（这里按“0列”处理，或可设为1列null）
                    // 但为了保持一致性，我们至少保留一行空列表
                    data.add(rowData); // 添加空行（无列）
                    continue;
                }

                // 获取该行最大物理列数（避免稀疏行问题）
                int lastCellNum = row.getLastCellNum();
                if (lastCellNum <= 0) {
                    // 行存在但无有效列
                    data.add(rowData);
                    continue;
                }

                // 遍历所有列（0 到 lastCellNum - 1）
                for (int colIndex = 0; colIndex < lastCellNum; colIndex++) {
                    Cell cell = row.getCell(colIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
                    Object cellValue = getCellValue(cell);
                    rowData.add(cellValue);
                }
                data.add(rowData);
            }
        }
        return data;
    }
//    // 跳过空行：
//    public static List<List<Object>> readToList(String filePath) throws IOException {
//        List<List<Object>> data = new ArrayList<>();
//
//        /*
//         * 使用 try-with-resources：
//         * try (FileInputStream fis = new FileInputStream(filePath)) {
//         *     Workbook wb = new XSSFWorkbook(fis);
//         *     // 自动关闭 fis（即使发生异常），不带try的话忘记关闭 fis → 文件句柄一直占用！
//         * }
//         * ✅ try ( ... ) 语法会在代码块结束时 自动调用 fis.close()，避免资源泄漏。
//         */
//        try (FileInputStream fis = new FileInputStream(filePath); //打开文件，准备读取其原始字节
//             Workbook workbook = getWorkbook(fis, filePath)) {    //把 Excel 文件“喂”给 POI 解析器
//
//            Sheet sheet = workbook.getSheetAt(0); // 读取第一个工作表
//
//            for (Row row : sheet) {
//                List<Object> rowData = new ArrayList<>();
//                // 获取该行最大物理列数（避免稀疏行问题）
//                int lastCellNum = row.getLastCellNum();
//                if (lastCellNum <= 0) {
//                    // 空行
//                    data.add(rowData);
//                    continue;
//                }
//
//                for (int i = 0; i < lastCellNum; i++) {
//                    Cell cell = row.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
//                    Object cellValue = getCellValue(cell);
//                    rowData.add(cellValue);
//                }
//                data.add(rowData);
//            }
//        }
//        return data;
//    }

    /**
     * 读取 Excel 文件，返回 Object[][]
     *
     * @param filePath 文件路径
     * @return 二维对象数组，空单元格为 null
     * @throws IOException 文件读取异常
     */
    public static Object[][] readToArray(String filePath) throws IOException {
        List<List<Object>> list = readToList(filePath);

        if (list.isEmpty()) {
            return new Object[0][0];
        }

        // 计算最大列数
        int maxCols = list.stream()
                .mapToInt(List::size)
                .max()
                .orElse(0);

        Object[][] array = new Object[list.size()][maxCols];
        for (int i = 0; i < list.size(); i++) {
            List<Object> row = list.get(i);
            for (int j = 0; j < row.size(); j++) {
                array[i][j] = row.get(j);
            }
        }
        return array;
    }

    // 根据文件扩展名创建对应的 Workbook
    private static Workbook getWorkbook(FileInputStream fis, String filePath) throws IOException {
        if (filePath.toLowerCase().endsWith(".xlsx")) {
            return new XSSFWorkbook(fis);
        } else if (filePath.toLowerCase().endsWith(".xls")) {
            return new HSSFWorkbook(fis);
        } else {
            throw new IllegalArgumentException("不支持的文件格式: " + filePath + "（仅支持 .xls 和 .xlsx）");
        }
    }

    /**
     * 将 Cell 转换为对应的 Java 对象
     *
     * @param cell 单元格
     * @return 对应的 Java 对象：
     *         - 字符串 → String
     *         - 数值 → Double（整数也返回 Double，如 123.0）
     *         - 布尔 → Boolean
     *         - 日期 → LocalDateTime（推荐）或 Date
     *         - 空/错误 → null
     */
    private static Object getCellValue(Cell cell) {
        if (cell == null || cell.getCellType() == CellType.BLANK) {
            return null;
        }

        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();

            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    // 转为 LocalDateTime（更现代）
                    Date date = cell.getDateCellValue();
                    return date.toInstant()
                            .atZone(ZoneId.systemDefault())
                            .toLocalDateTime();
                } else {
                    // 返回 Double（POI 默认行为）
                    return cell.getNumericCellValue();
                }

            case BOOLEAN:
                return cell.getBooleanCellValue();

            case FORMULA:
                // 尝试按公式结果类型返回
                try {
                    switch (cell.getCachedFormulaResultType()) {
                        case STRING:
                            return cell.getStringCellValue();
                        case NUMERIC:
                            if (DateUtil.isCellDateFormatted(cell)) {
                                Date date = cell.getDateCellValue();
                                return date.toInstant()
                                        .atZone(ZoneId.systemDefault())
                                        .toLocalDateTime();
                            } else {
                                return cell.getNumericCellValue();
                            }
                        case BOOLEAN:
                            return cell.getBooleanCellValue();
                        default:
                            return null;
                    }
                } catch (Exception e) {
                    return null; // 公式计算失败
                }

            case ERROR:
            default:
                return null;
        }
    }
}
